package com.example.interesting.distributed.lock.realize.strategy;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author fyw
 * @version 1.0
 * @description: 分布式key默认生成策略
 * @date 2024/3/16 13:20
 */
public class DefaultDistributedLockKeyBuilder implements DistributedLockKeyBuilder {

    /**
     * 在运行时发现方法和构造函数的参数名称 TODO: 2024/3/16 13:21
     */
    private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
    /**
     * Spel解析表达式
     */
    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();

    private BeanResolver beanResolver;

    public DefaultDistributedLockKeyBuilder(BeanFactory beanFactory) {
        this.beanResolver = new BeanFactoryResolver(beanFactory);
    }

    @Override
    public String buildKey(MethodInvocation invocation, String[] keys) {
        if (!ObjectUtils.isEmpty(keys)) {
            return convertKeys(invocation, keys);
        }
        return "";
    }


    protected String convertKeys(MethodInvocation invocation, String[] keys) {
        //创建Spel解析的参数上下文
        StandardEvaluationContext standardContext = new MethodBasedEvaluationContext(invocation.getThis(),
                invocation.getMethod(), invocation.getArguments(), PARAMETER_NAME_DISCOVERER);
        standardContext.setBeanResolver(beanResolver);
        //定义结果变量
        List<String> result = new ArrayList<>(keys.length);
        for (String key : keys) {
            //默认都按字符串处理
            if (key != null && !key.isEmpty()) {
                result.add(EXPRESSION_PARSER.parseExpression(key).getValue(standardContext, String.class));
            }
        }
        return StringUtils.collectionToDelimitedString(result, ".");
    }
}
